package hhs.scannerapp;


import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;


import android.os.Environment;
import android.util.Log;

public class Parser {
	public static File toObj(String fileName, Cube cube) {
		Log.d("OpenCVTest", "Saving .obj model...");
		// Create a File for saving the image
		boolean haveDir = true;
		File mediaStorageDir = new File(Environment.getExternalStorageDirectory().getPath(),"Models");
		File objFile = null;

		if (!mediaStorageDir.exists())
		{
			if (!mediaStorageDir.mkdirs())
			{
				haveDir = false;
				return null;
			}
		}

		if(haveDir)
		{
			objFile = new File(mediaStorageDir.getPath() + File.separator + fileName + ".obj");
		}

		if (objFile == null)
		{
			Log.d("Model Callback", "Error creating .obj file");
		}
		else
		{
			try
			{
				FileWriter fw = new FileWriter(objFile);
				fw.write("#The units used in file are in TODO-What units?\n");

				for(int i = 2; i < cube.vertices.length; i+=3){
					fw.write("v " + cube.vertices[i-2] + " " +
									cube.vertices[i-1] + " " +
									cube.vertices[i] + "\n");
				}

				fw.write("\n");

				for(int i = 0; i < cube.indexes.length/3; i++) {
					fw.write("f "+(cube.indexes[3*i]+1)+" "+(cube.indexes[3*i+1]+1)+" "+(cube.indexes[3*i+2]+1)+"\n");
				}
				
				for(int i = 0; i < cube.topIndexes.length/3; i++) {
					fw.write("f "+(cube.topIndexes[3*i]+1)+" "+(cube.topIndexes[3*i+1]+1)+" "+(cube.topIndexes[3*i+2]+1)+"\n");
				}
				
				fw.close();
			}
			catch (FileNotFoundException e)
			{
				Log.d("PictureCallback", "File not found: " + e.getMessage());
			}
			catch (IOException e)
			{
				Log.d("PictureCallback", "Error accessing file: " + e.getMessage());
			}
		}

		return objFile;
	}
	
	public static File toObj(String fileName, Model model){
		Log.d("OpenCVTest", "Saving .obj model...");
		// Create a File for saving the image
//		boolean haveDir = true;
//		File mediaStorageDir = new File(Environment.getExternalStorageDirectory().getPath(),"Models");
		File objFile = null;

//		if (!mediaStorageDir.exists())
//		{
//			if (!mediaStorageDir.mkdirs())
//			{
//				haveDir = false;
//				return null;
//			}
//		}

//		if(haveDir)
//		{
			objFile = new File(fileName + ".obj");
//		}

//		if (objFile == null)
//		{
//			Log.d("Model Callback", "Error creating .obj file");
//		}
//		else
//		{
			try
			{
				FileWriter fw = new FileWriter(objFile);
				fw.write("#The units used in file are in TODO-What units?\n");

				for(int i = 2; i < model.vertices.length; i+=3){
					fw.write("v " + model.vertices[i-2] + " " +
							model.vertices[i-1] + " " +
							model.vertices[i] + "\n");
				}

				fw.write("\n");

				for(int i = 0; i < model.nEdges; i++) {
					for(int j = 0; j < 2*model.edgeSize-2; j++) {
						if(j%2==0) {
							fw.write("f "+ (model.indexes[i][j]+1)  +" "+
										   (model.indexes[i][j+1]+1)+" "+
										   (model.indexes[i][j+2]+1)+"\n");
						} else {
							fw.write("f "+ (model.indexes[i][j+2]+1)  +" "+
									       (model.indexes[i][j+1]+1)+" "+
									       (model.indexes[i][j]+1)+"\n");
						}
					}
				}

				for(int i = model.nEdges; i < model.indexes.length; i++) {
					if(i == model.nEdges) {
						for(int j = 1; j < model.indexes[i].length-1; j++) {
							fw.write("f "+ (model.indexes[i][j]+1) + " "+
									       (model.indexes[i][0]+1) + " "+
										   (model.indexes[i][j+1]+1)+"\n");
						}
					} else {
						for(int j = 1; j < model.indexes[i].length-1; j++) {
							fw.write("f "+ (model.indexes[i][0]+1) + " "+
									       (model.indexes[i][j]+1) + " "+
										   (model.indexes[i][j+1]+1)+"\n");
						}
					}
				}
				
				fw.close();
			}
			catch (FileNotFoundException e)
			{
				Log.d("PictureCallback", "File not found: " + e.getMessage());
			}
			catch (IOException e)
			{
				Log.d("PictureCallback", "Error accessing file: " + e.getMessage());
			}
//		}

		return objFile;
	}

	public static File toSTL(String fileName, Cube cube) {
		boolean haveDir = true;
		File mediaStorageDir = new File(Environment.getExternalStorageDirectory().getPath(),"Models");
		File stlFile = null;

		if (!mediaStorageDir.exists())
		{
			if (!mediaStorageDir.mkdirs())
			{
				haveDir = false;
				return null;
			}
		}

		if(haveDir)
		{
			stlFile = new File(mediaStorageDir.getPath() + File.separator + fileName + ".stl");
		}

		if (stlFile == null)
		{
			Log.d("Model Callback", "Error creating .stl file");
		}
		else
		{
			try
			{
				FileWriter fw = new FileWriter(stlFile);
				fw.write("solid \n");		

				for(int i = 0; i < cube.indexes.length/3; i++) {
					fw.write("  facet normal 0 0 0 \n");
					fw.write("    outer loop\n");
					writeIndex(fw,cube.indexes[3*i],cube);
					writeIndex(fw,cube.indexes[3*i+1],cube);
					writeIndex(fw,cube.indexes[3*i+2],cube);					
					fw.write("    endloop \n");
					fw.write("  endfacet \n");
				}
				
				for(int i = 0; i < cube.topIndexes.length/3; i++) {
					fw.write("  facet normal 0 0 0 \n");
					fw.write("    outer loop\n");
					writeIndex(fw,cube.topIndexes[3*i],cube);
					writeIndex(fw,cube.topIndexes[3*i+1],cube);
					writeIndex(fw,cube.topIndexes[3*i+2],cube);	
					fw.write("    endloop \n");
					fw.write("  endfacet \n");
				}
				
				fw.write("endsolid");

				fw.close();
			}
			catch (FileNotFoundException e)
			{
				Log.d("PictureCallback", "File not found: " + e.getMessage());
			}
			catch (IOException e)
			{
				Log.d("PictureCallback", "Error accessing file: " + e.getMessage());
			}
		}

		return stlFile;
	}
	
	public static File toSTL(String fileName, Model model){
		Log.d("OpenCVTest", "Saving .stl model...");
		// Create a File for saving the image
//		boolean haveDir = true;
//		File mediaStorageDir = new File(Environment.getExternalStorageDirectory().getPath(),"Models");
		File stlFile = null;

//		if (!mediaStorageDir.exists())
//		{
//			if (!mediaStorageDir.mkdirs())
//			{
//				haveDir = false;
//				return null;
//			}
//		}

//		if(haveDir)
//		{
			stlFile = new File(fileName + ".stl");
//		}

//		if (stlFile == null)
//		{
//			Log.d("Model Callback", "Error creating .stl file");
//		}
//		else
//		{
			try
			{
				FileWriter fw = new FileWriter(stlFile);
				fw.write("solid \n");
				for(int i = 0; i < model.nEdges; i++){
					for(int j = 0; j < 2*model.edgeSize-2; j++) {
						fw.write("  facet normal 0 0 0 \n");
						fw.write("    outer loop\n");
						boolean even = j%2 == 0;
						if(even) {
							for(int k = 0; k < 3; k++) {
								int index = 3*model.indexes[i][j+k];
								fw.write("      vertex " +model.vertices[index] +" "+model.vertices[index+1] +" "+model.vertices[index+2]+"\n");
							}
						} else {
							for(int k = 2; k >= 0; k--) {
								int index = 3*model.indexes[i][j+k];
								fw.write("      vertex " +model.vertices[index] +" "+model.vertices[index+1] +" "+model.vertices[index+2]+"\n");
							}	
						}
						fw.write("    endloop \n");
						fw.write("  endfacet \n");
					}
				}
				for(int i = model.nEdges; i < model.indexes.length; i++) {
					if(i == model.nEdges) {
						for(int j = 1; j < model.indexes[i].length-1; j++) {
							fw.write("  facet normal 0 0 0 \n");
							fw.write("    outer loop\n");
							writeIndex(fw, model.indexes[i][j], model);
							writeIndex(fw, model.indexes[i][0], model);
							writeIndex(fw, model.indexes[i][j+1], model);
							fw.write("    endloop \n");
							fw.write("  endfacet \n");
						}
					} else {
						for(int j = 1; j < model.indexes[i].length-1; j++) {
							fw.write("  facet normal 0 0 0 \n");
							fw.write("    outer loop\n");
							writeIndex(fw, model.indexes[i][0], model);
							writeIndex(fw, model.indexes[i][j], model);
							writeIndex(fw, model.indexes[i][j+1], model);
							fw.write("    endloop \n");
							fw.write("  endfacet \n");
						}
					}
				}
				
				fw.write("endsolid");

				fw.close();
			}
			catch (FileNotFoundException e)
			{
				Log.d("PictureCallback", "File not found: " + e.getMessage());
			}
			catch (IOException e)
			{
				Log.d("PictureCallback", "Error accessing file: " + e.getMessage());
			}
//		}

		return stlFile;
	}
	
	private static void writeIndex(FileWriter fw, int index, Model model) throws IOException {
		fw.write("      vertex " +model.vertices[3*index] +" "+model.vertices[3*index+1] +" "+model.vertices[3*index+2]+"\n");
	}
	
	private static void writeIndex(FileWriter fw, int index, Cube cube) throws IOException {
		fw.write("      vertex " +cube.vertices[3*index] +" "+cube.vertices[3*index+1] +" "+cube.vertices[3*index+2]+"\n");
	}

	public static File toX3D(String fileName, Model model){
		File x3dFile = Parser.toObj(fileName, model);
		return x3dFile;
	}

	public static File toDae(String fileName, Model model){
		File daeFile = Parser.toObj(fileName, model);
		return daeFile;
	}


	/** Create a File for saving the file */
	private static File getOutputFile(String fileName)
	{
		boolean haveDir = true;
		File mediaStorageDir = new File(Environment.getExternalStorageDirectory().getPath(),"Models");
		File mediaFile = null;

		if (!mediaStorageDir.exists())
		{
			if (!mediaStorageDir.mkdirs())
			{
				haveDir = false;
				return null;
			}
		}

		if(haveDir)
		{
			mediaFile = new File(mediaStorageDir.getPath() + File.separator + fileName+ ".obj");
		}

		return mediaFile;
	}
}
